﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.ServiceModel.DomainServices.Client.ApplicationServices;
using System.Windows;
using System.Windows.Input;
using Microsoft.Practices.Prism.Commands;
using Microsoft.Practices.Prism.Regions;
using Microsoft.Practices.Unity;
using VS.Web.Model;

namespace VS.MainModule.Views
{
    public class LoginViewModel : INotifyPropertyChanged, INavigationAware, IEditableObject
    {
        #region Fields
        private IRegionNavigationService _navigationService;
        private AuthenticationService _service = WebContext.Current.Authentication;
        private AuthenticationOperation _op;
        #endregion

        #region Properties

        [Dependency]
        public IRegionManager RegionManager { get; set; }

        private string _login;
        [Required(AllowEmptyStrings = false)]
        [StringLength(50, MinimumLength = 3)]
        public string Login
        {
            get { return _login; }
            set
            {
                _login = value;
                OnPropertyChanged("Login");
            }
        }

        private string _password;
        [Required(AllowEmptyStrings = false)]
        [StringLength(32, MinimumLength = 6)]
        public string Password
        {
            get { return _password; }
            set
            {
                _password = value;
                OnPropertyChanged("Password");
            }
        }

        public User User { get; set; }

        private ObservableCollection<Exception> _errors;
        public ObservableCollection<Exception> Errors
        {
            get { return _errors; }
            set { _errors = value; OnPropertyChanged("Errors"); }
        }

        private Visibility _errorsVisibility;
        public Visibility ErrorsVisibility
        {
            get { return _errorsVisibility; }
            set { _errorsVisibility = value; OnPropertyChanged("ErrorsVisibility"); }
        }

        public ICommand CancelLogin { get; set; }
        public ICommand ValidateLogin { get; set; }

        #endregion

        #region ctor
        public LoginViewModel()
        {
            Errors = new ObservableCollection<Exception>();
            CancelLogin = new DelegateCommand(GoBack);
            ErrorsVisibility = Visibility.Collapsed;

            ValidateLogin = new DelegateCommand(() =>
            {
                _service.Login(new LoginParameters(Login, Password, true, null), LoginOperationCompleted, null);
            });

        }
        #endregion

        #region Methods

        private void LoginOperationCompleted(LoginOperation lo)
        {
            Errors.Clear();                         
            if (lo.HasError)
            {
                ErrorsVisibility = Visibility.Visible;
                GetErrorStack(lo.Error).ToList().ForEach(x => Errors.Add(x));
            }
            else if (lo.LoginSuccess == false)
            {                
            }
            else if (lo.LoginSuccess == true)
            {                
            }

            GoBack();
        }

        private IEnumerable<Exception> GetErrorStack(Exception e)
        {
            if (e == null) yield break;
            foreach (Exception item in GetErrorStack(e.InnerException)) yield return item;
            yield return e;
        }

        private void GoBack()
        {
            if (_navigationService.Journal.CanGoBack)
                _navigationService.Journal.GoBack();
            else
                _navigationService.RequestNavigate("/main");
        }

        #endregion

        #region INotifyPropertyChanged Members

        public event PropertyChangedEventHandler PropertyChanged;

        protected virtual void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }

        #endregion


        public void OnNavigatedTo(NavigationContext navigationContext)
        {
            _navigationService = navigationContext.NavigationService;
        }

        public bool IsNavigationTarget(NavigationContext navigationContext)
        {
            return true;
        }

        public void OnNavigatedFrom(NavigationContext navigationContext)
        {
        }

        public void BeginEdit()
        {
        }

        public void CancelEdit()
        {
            CancelLogin.Execute(null);
        }

        public void EndEdit()
        {
            ValidateLogin.Execute(null);
        }
    }
}
